﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Web.Http;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ShoppingCart.WebApi;
using ShoppingCart.WebApi.Controllers;
using Newtonsoft.Json.Linq;
using System.Net;
using System.Diagnostics;

namespace ShoppingCart.WebApi.Tests.Controllers
{
    [TestClass]
    public class ShoppingCartTest
    {
        String encodedTestUserId = "dXNlcjFAaG90bWFpbC5jb20=";
        String testProdId = "101";

        private static HttpClient GetHttpClient()
        {
            HttpClient client = new HttpClient();
            client.BaseAddress = new Uri("http://localhost:61563/");
            return client;
        }

        private HttpResponseMessage InsertCartRecord(bool valid)
        {
            JObject json;
            if (valid)
                json = JObject.Parse(@"{""userId"" : ""user1@hotmail.com"",""items"" : [{""prodId"" : ""5168bed10fdb8c0e7c671d32"",""prodName"" : ""NoSQL Distilled"",""prodDesc"" : ""A brief guide to the emerging world of polyglot persistence."",""prodPrice"" : 24.99,""quantity"" : 1,""imageUrl"": ""/productimages/101.png"",},{""prodId"" : ""5168f7310fdb8c13e46a6c61"",""prodName"" : ""Seven Databases in Seven Weeks"",""prodDesc"" : ""A guide to modern databases and the NoSQL movement"",""prodPrice"" : 26.99,""quantity"" : 1,""imageUrl"": ""/productimages/102.png""}]}");
            else
                json = JObject.Parse(@"{""Wrong key"":""Wrong value""}");
            var client = GetHttpClient();
            return client.PostAsJsonAsync("/api/cart", json).Result;
        }

        private HttpResponseMessage InsertCartItemRecord(bool valid)
        {
            JObject json;
            if (valid)
                json = JObject.Parse(@"{""prodId"" : 101,""prodName"" : ""NoSQL Distilled"",""prodDesc"" : ""A brief guide to the emerging world of polyglot persistence."",""prodPrice"" : 24.99,""quantity"" : 1,""imageUrl"": ""/productimages/101.png"",}");
            else
                json = JObject.Parse(@"{""Wrong key"":""Wrong value""}");
            var client = GetHttpClient();
            return client.PostAsJsonAsync("/api/cart/" + encodedTestUserId + "/items/101", json).Result;
        }

        private HttpResponseMessage UpdateCartItemRecord(bool valid)
        {
            JObject json;
            if (valid)
                json = JObject.Parse(@"{""prodId"" : 101,""prodName"" : ""new"",""prodDesc"" : ""new."",""prodPrice"" : 99.99,""quantity"" : 10,""imageUrl"": ""/productimages/101new.png"",}");
            else
                json = JObject.Parse(@"{""Wrong key"":""Wrong value""}");
            var client = GetHttpClient();
            return client.PutAsJsonAsync("/api/cart/" + encodedTestUserId + "/items/101", json).Result;
        }

        [TestMethod]
        public void GetShoppingCart()
        {
            InsertCartRecord(true);
            var client = GetHttpClient();
            HttpResponseMessage response = client.GetAsync("api/cart/" + encodedTestUserId).Result;
            Assert.IsTrue(response.StatusCode == HttpStatusCode.OK);
            string responseBody = response.Content.ReadAsStringAsync().Result;
            Trace.WriteLine(responseBody);
        }

        [TestMethod]
        public void AddShoppingCart()
        {
            HttpResponseMessage response = InsertCartRecord(true);
            string responseBody = response.Content.ReadAsStringAsync().Result;
            Trace.WriteLine(responseBody);
            Assert.IsTrue(response.StatusCode == HttpStatusCode.Created);

            response = InsertCartRecord(false);
            Assert.IsTrue(response.StatusCode == HttpStatusCode.BadRequest);
        }
        
        [TestMethod]
        public void DeleteShoppingCart()
        {
            InsertCartRecord(true);
            var client = GetHttpClient();
            HttpResponseMessage response = client.DeleteAsync("api/cart/" + encodedTestUserId).Result;
            Assert.IsTrue(response.StatusCode == HttpStatusCode.OK);

            response = client.DeleteAsync("api/cart/xxxx").Result;
            Assert.IsTrue(response.StatusCode == HttpStatusCode.NotFound);
        }

        [TestMethod]
        public void GetShoppingCartItem()
        {
            InsertCartItemRecord(true);
            var client = GetHttpClient();
            HttpResponseMessage response = client.GetAsync("api/cart/" + encodedTestUserId + "/items/"+testProdId).Result;
            Assert.IsTrue(response.StatusCode == HttpStatusCode.OK);
            string responseBody = response.Content.ReadAsStringAsync().Result;
            Trace.WriteLine(responseBody);
        }


        [TestMethod]
        public void AddShoppingCartItem()
        {
            HttpResponseMessage response = InsertCartItemRecord(true);
            Assert.IsTrue(response.StatusCode == HttpStatusCode.Created);
            string responseBody = response.Content.ReadAsStringAsync().Result;
            Trace.WriteLine(responseBody);

            response = InsertCartItemRecord(true);
            Assert.IsTrue(response.StatusCode == HttpStatusCode.Created);
            responseBody = response.Content.ReadAsStringAsync().Result;
            Trace.WriteLine(responseBody);

            response = InsertCartItemRecord(false);
            Assert.IsTrue(response.StatusCode == HttpStatusCode.BadRequest);
        }

        [TestMethod]
        public void UpdateShoppingCartItem()
        {
            //show current item quantity
            var client = GetHttpClient();
            HttpResponseMessage response = client.GetAsync("api/cart/" + encodedTestUserId + "/items/" + testProdId).Result;
            Assert.IsTrue(response.StatusCode == HttpStatusCode.OK);
            string responseBody = response.Content.ReadAsStringAsync().Result;
            Trace.WriteLine(responseBody);

            //add one more
            response = UpdateCartItemRecord(true);
            Assert.IsTrue(response.StatusCode == HttpStatusCode.Created);
            responseBody = response.Content.ReadAsStringAsync().Result;
            Trace.WriteLine(responseBody);

            //show current item quantity
            response = client.GetAsync("api/cart/" + encodedTestUserId + "/items/" + testProdId).Result;
            Assert.IsTrue(response.StatusCode == HttpStatusCode.OK);
            responseBody = response.Content.ReadAsStringAsync().Result;
            Trace.WriteLine(responseBody);

            response = InsertCartItemRecord(false);
            Assert.IsTrue(response.StatusCode == HttpStatusCode.BadRequest);
        }

        [TestMethod]
        public void DeleteShoppingCartItem()
        {
            InsertCartItemRecord(true);
            var client = GetHttpClient();
            HttpResponseMessage response = client.DeleteAsync("api/cart/" + encodedTestUserId + "/items/" + testProdId).Result;
            Assert.IsTrue(response.StatusCode == HttpStatusCode.OK);

            response = client.DeleteAsync("api/cart/" + encodedTestUserId + "/items/xxx").Result;
            Assert.IsTrue(response.StatusCode == HttpStatusCode.NotFound);
        }
    }
}
